
//Copyright 1997-2009 Syrinx Development, Inc.
//This file is part of the Syrinx Web Application Framework (SWAF).
// == BEGIN LICENSE ==
//
// Licensed under the terms of any of the following licenses at your
// choice:
//
//  - GNU General Public License Version 3 or later (the "GPL")
//    http://www.gnu.org/licenses/gpl.html
//
//  - GNU Lesser General Public License Version 3 or later (the "LGPL")
//    http://www.gnu.org/licenses/lgpl.html
//
//  - Mozilla Public License Version 1.1 or later (the "MPL")
//    http://www.mozilla.org/MPL/MPL-1.1.html
//
// == END LICENSE ==
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;

using Swaf;
using Swaf.BizObj;
using Swaf.BizRule;
using Swaf.Container;
using Swaf.Security;

using ICSharpCode.SharpZipLib.Zip.Compression;
using ICSharpCode.SharpZipLib.Zip.Compression.Streams;
using ICSharpCode.SharpZipLib.GZip;
using ICSharpCode.SharpZipLib.Zip;
using ICSharpCode.SharpZipLib.Checksums;
using ICSharpCode.SharpZipLib.Core;

namespace eCom
{
	public class eComRestoreBizRules : Syrinx.BaseBizRules
	{
		public void restoreCompanyProducts(IApplication app, IRuleContext context, IBizObj bkInfo, ZipFile zipFile)
		{
			IBizObjList restoreCompanies = (IBizObjList)bkInfo.get("restoreCompanies");
			IBizObjList backupCompanies = (IBizObjList)bkInfo.get("backupCompanies");
			//We need to change the active company id to the company that the backup is for so that
			//any reference to the activeCompanyId in the following company will point to the correct company.
			Swaf.BGuid.Guid oldCmpId = ActiveCompanyId;
			try
			{
				for (int pos = 0; pos < restoreCompanies.numElements; ++pos)
				{
					IBizObj restoreCompany = restoreCompanies[pos];
					IBizObj backupCompany = backupCompanies.numElements == 1 ? backupCompanies[0] : backupCompanies[pos];
					bool restoreToSameCompany = string.Compare((string)backupCompany.get("shortName"), (string)restoreCompany.get("shortName")) == 0;
					ActiveCompanyId = restoreCompany.get("id") as Swaf.BGuid.Guid;
					try
					{
						Dictionary<Swaf.BGuid.Guid, Swaf.BGuid.Guid> m_idDict = context.get("IdMap" + restoreCompany.get("shortName")) as Dictionary<Swaf.BGuid.Guid, Swaf.BGuid.Guid>;
						if (m_idDict == null)
							context.put("IdMap" + restoreCompany.get("shortName"), m_idDict = new Dictionary<Swaf.BGuid.Guid, Swaf.BGuid.Guid>());

						string desiredArticlePath = string.Format("data{0}{1}{0}Products{0}", Path.DirectorySeparatorChar, backupCompany.get("shortName"));
						foreach (ZipEntry entry in zipFile)
						{
							string entryName = entry.Name;
							if (entry.IsFile && entryName.StartsWith(desiredArticlePath))
							{
								StreamReader sr = new StreamReader(zipFile.GetInputStream(entry));
								string file = sr.ReadToEnd();
								IBizObjList articles = app.bizObjMgr.createList(SourceType.BasicSource, file, "eComProduct", null);
								foreach (IBizObj article in articles)
								{
									IBizObj existArt = context.RuleGroup.execute(context, "findArticle",
										restoreCompany.get("id"), article.get("id"), article.get("uniqueTitle"), article.get("keyName"), article.get("treeName")).CallResults as IBizObj;
									IBizObj existParent = null;
									if (existArt == null)
									{
										string parentKeyName = (string)article.get("keyName");
										int lastIndex;
										while ((lastIndex = parentKeyName.LastIndexOf('\xd')) != -1 && existParent == null)
											existParent = context.RuleGroup.execute(context, "findArticle",
												restoreCompany.get("id"), null,
												null, parentKeyName = parentKeyName.Substring(0, lastIndex), article.get("treeName")).CallResults as IBizObj;

										if (existParent != null)
										{
											existArt = context.RuleGroup.execute(context, "findArticle",
												restoreCompany.get("id"), article.get("id"), article.get("uniqueTitle"),
												parentKeyName + "\xd" + article.get("name"), article.get("treeName")).CallResults as IBizObj;
										}
									}
									article.setAllFieldsDirty();

									object parentId = existArt == null ? existParent == null ? null : existParent.get("id") : existArt.get("parentId");
									if (!m_idDict.ContainsKey(article.get("id") as Swaf.BGuid.Guid))
										m_idDict.Add(article.get("id") as Swaf.BGuid.Guid, (Swaf.BGuid.Guid)(existArt != null ? existArt.get("id") : new Swaf.BGuid.Guid()));

									if (!m_idDict.ContainsKey(article.get("parentId") as Swaf.BGuid.Guid))
										m_idDict.Add(article.get("parentId") as Swaf.BGuid.Guid, parentId as Swaf.BGuid.Guid);

									if (!m_idDict.ContainsKey(article.get("objectId") as Swaf.BGuid.Guid))
										m_idDict.Add(article.get("objectId") as Swaf.BGuid.Guid,
											(Swaf.BGuid.Guid)(existArt == null ? m_idDict[article.get("id") as Swaf.BGuid.Guid] : existArt.get("objectId")));

									if (!m_idDict.ContainsKey(article.get("parentHostId") as Swaf.BGuid.Guid))
										m_idDict.Add(article.get("parentHostId") as Swaf.BGuid.Guid,
											(Swaf.BGuid.Guid)(existArt == null ? existParent == null ? m_idDict[article.get("id") as Swaf.BGuid.Guid] : existParent.get("parentHostId") : existArt.get("parentHostId")));

									if (!m_idDict.ContainsKey(article.get("rootId") as Swaf.BGuid.Guid))
										m_idDict.Add(article.get("rootId") as Swaf.BGuid.Guid,
											(Swaf.BGuid.Guid)(existArt == null ? existParent == null ? m_idDict[article.get("id") as Swaf.BGuid.Guid] : existParent.get("rootId") : existArt.get("rootId")));

									article.put("id", m_idDict[article.get("id") as Swaf.BGuid.Guid]);
									article.put("parentId", m_idDict[article.get("parentId") as Swaf.BGuid.Guid]);
									article.put("objectId", m_idDict[article.get("objectId") as Swaf.BGuid.Guid]);
									article.put("parentHostId", m_idDict[article.get("parentHostId") as Swaf.BGuid.Guid]);
									article.put("rootId", m_idDict[article.get("rootId") as Swaf.BGuid.Guid]);
									article.put("companyId", restoreCompany.get("id"));
									if (existArt != null)
										article.put("treeName", existArt.get("treeName"));
									article.isNew = existArt == null;
									if (existArt != null && parentId != null && ((IComparable)parentId).CompareTo(existArt.get("parentId")) == 0)
										article.setDirtyFlag("parentId", false);
									if (existArt != null && ((IComparable)article.get("baseTitle")).CompareTo(existArt.get("baseTitle")) == 0)
										article.setDirtyFlag("baseTitle", false);

									context.RuleGroup.execute("updateProduct", article);
								}
							}
						}
					}
					catch (Exception e)
					{
						throw new eComException("error executing restoreCompanyProducts", e);
					}
				}
			}
			finally
			{
				ActiveCompanyId = oldCmpId;
			}
		}

		public void restoreCheckoutWizards(IApplication app, IRuleContext context, IBizObj bkInfo, ZipFile zipFile)
		{
			IBizObjList restoreCompanies = (IBizObjList)bkInfo.get("restoreCompanies");
			IBizObjList backupCompanies = (IBizObjList)bkInfo.get("backupCompanies");
			//We need to change the active company id to the company that the backup is for so that
			//any reference to the activeCompanyId in the following company will point to the correct company.
			Swaf.BGuid.Guid oldCmpId = ActiveCompanyId;
			try
			{
				for (int pos = 0; pos < restoreCompanies.numElements; ++pos)
				{
					IBizObj restoreCompany = restoreCompanies[pos];
					IBizObj backupCompany = backupCompanies.numElements == 1 ? backupCompanies[0] : backupCompanies[pos];
					bool restoreToSameCompany = string.Compare((string)backupCompany.get("shortName"), (string)restoreCompany.get("shortName")) == 0;

					Dictionary<Swaf.BGuid.Guid, Swaf.BGuid.Guid> m_idDict = context.get("IdMap" + restoreCompany.get("shortName")) as Dictionary<Swaf.BGuid.Guid, Swaf.BGuid.Guid>;
					if (m_idDict == null)
						context.put("IdMap" + restoreCompany.get("shortName"), m_idDict = new Dictionary<Swaf.BGuid.Guid, Swaf.BGuid.Guid>());

					string searchFile = string.Format("data{0}{1}{0}PreCheckoutWizardSteps.xml", Path.DirectorySeparatorChar, backupCompany.get("shortName"));
					foreach (ZipEntry entry in zipFile)
					{
						string entryName = entry.Name;
						if (entry.IsFile && entryName.CompareTo(searchFile)==0)
						{
								StreamReader sr = new StreamReader(zipFile.GetInputStream(entry));
								string file = sr.ReadToEnd();
								IBizObjList steps = app.bizObjMgr.createList(SourceType.BasicSource, file, "eComCheckoutWizardStep", null);
								foreach (IBizObj step in steps)
								{
									step.put("companyId", restoreCompany.get("id"));
									if (m_idDict.ContainsKey(step.get("product.id") as Swaf.BGuid.Guid))
										step.put("product.id", m_idDict[step.get("product.id") as Swaf.BGuid.Guid]);
									context.RuleGroup.execute(context, "deletePreCheckOutWizard", step);

									if (m_idDict.ContainsKey(step.get("id") as Swaf.BGuid.Guid))
										step.put("id", m_idDict[step.get("id") as Swaf.BGuid.Guid]);
									context.RuleGroup.execute(context, "addPreCheckOutWizard", step);
								}

						}
					}
				}
			}
			catch (Exception e)
			{
				throw new eComException("error executing restoreCompanyProducts", e);
			}
		}

		public void restorePaymentTerms(IApplication app, IRuleContext context, IBizObj bkInfo, ZipFile zipFile)
		{
			IBizObjList restoreCompanies = (IBizObjList)bkInfo.get("restoreCompanies");
			IBizObjList backupCompanies = (IBizObjList)bkInfo.get("backupCompanies");
			//We need to change the active company id to the company that the backup is for so that
			//any reference to the activeCompanyId in the following company will point to the correct company.
			Swaf.BGuid.Guid oldCmpId = ActiveCompanyId;
			try
			{
				for (int pos = 0; pos < restoreCompanies.numElements; ++pos)
				{
					IBizObj restoreCompany = restoreCompanies[pos];
					IBizObj backupCompany = backupCompanies.numElements == 1 ? backupCompanies[0] : backupCompanies[pos];
					bool restoreToSameCompany = string.Compare((string)backupCompany.get("shortName"), (string)restoreCompany.get("shortName")) == 0;
					Dictionary<Swaf.BGuid.Guid, Swaf.BGuid.Guid> m_idDict = context.get("IdMap" + restoreCompany.get("shortName")) as Dictionary<Swaf.BGuid.Guid, Swaf.BGuid.Guid>;
					if (m_idDict == null)
						context.put("IdMap" + restoreCompany.get("shortName"), m_idDict = new Dictionary<Swaf.BGuid.Guid, Swaf.BGuid.Guid>());

					string searchFile = string.Format("data{0}{1}{0}CompanyPaymentTerms.xml", Path.DirectorySeparatorChar, backupCompany.get("shortName"));
					string userTermsFile = string.Format("data{0}{1}{0}UserPaymentTerms.xml", Path.DirectorySeparatorChar, backupCompany.get("shortName"));
					foreach (ZipEntry entry in zipFile)
					{
						string entryName = entry.Name;
						if (entry.IsFile && entryName.CompareTo(searchFile) == 0)
						{
							StreamReader sr = new StreamReader(zipFile.GetInputStream(entry));
							string file = sr.ReadToEnd();
							IBizObjList terms = app.bizObjMgr.createList(SourceType.BasicSource, file, "eComPaymentTerm", null);
							foreach (IBizObj term in terms)
							{
								term.isNew = false;
								context.RuleGroup.execute(context, "updateCompanyPaymentTerm", restoreCompany.get("id"), term);
							}
						}
						else if (entry.IsFile && entryName.CompareTo(userTermsFile) == 0)
						{
							StreamReader sr = new StreamReader(zipFile.GetInputStream(entry));
							string file = sr.ReadToEnd();
							IBizObjList terms = app.bizObjMgr.createList(SourceType.BasicSource, file, "eComPaymentTerm", null);
							foreach (IBizObj term in terms)
							{
								//When restoring a backup to the SAME company the backup was created from, the ids should
								//not be reset.  That way, we will restore OVER EXISTING data, which is what would
								//be wanted when restoring a backup in the same company.
								if (!restoreToSameCompany)
								{
									Swaf.BGuid.Guid g = null;
									if (!m_idDict.TryGetValue(term.get("userId") as Swaf.BGuid.Guid, out g))
										m_idDict.Add(term.get("userId") as Swaf.BGuid.Guid, g = new Swaf.BGuid.Guid());
									term.put("userId", g);
								}

								term.isNew = false;
								context.RuleGroup.execute(context, "updateUserPaymentTerm", term);
							}
						}
					}
				}
			}
			catch (Exception e)
			{
				throw new eComException("error executing restoreCompanyProducts", e);
			}
		}

		public void restoreTaxesDiscounts(IApplication app, IRuleContext context, IBizObj bkInfo, ZipFile zipFile)
		{
			IBizObjList restoreCompanies = (IBizObjList)bkInfo.get("restoreCompanies");
			IBizObjList backupCompanies = (IBizObjList)bkInfo.get("backupCompanies");
			//We need to change the active company id to the company that the backup is for so that
			//any reference to the activeCompanyId in the following company will point to the correct company.
			Swaf.BGuid.Guid oldCmpId = ActiveCompanyId;
			try
			{
				for (int pos = 0; pos < restoreCompanies.numElements; ++pos)
				{
					IBizObj restoreCompany = restoreCompanies[pos];
					IBizObj backupCompany = backupCompanies.numElements == 1 ? backupCompanies[0] : backupCompanies[pos];
					bool restoreToSameCompany = string.Compare((string)backupCompany.get("shortName"), (string)restoreCompany.get("shortName")) == 0;
				}
			}
			catch (Exception e)
			{
				throw new eComException("error executing restoreCompanyProducts", e);
			}
		}

		public void restoreSalesOrders(IApplication app, IRuleContext context, IBizObj bkInfo, ZipFile zipFile)
		{
			IBizObjList restoreCompanies = (IBizObjList)bkInfo.get("restoreCompanies");
			IBizObjList backupCompanies = (IBizObjList)bkInfo.get("backupCompanies");
			//We need to change the active company id to the company that the backup is for so that
			//any reference to the activeCompanyId in the following company will point to the correct company.
			Swaf.BGuid.Guid oldCmpId = ActiveCompanyId;
			try
			{
				for (int pos = 0; pos < restoreCompanies.numElements; ++pos)
				{
					IBizObj restoreCompany = restoreCompanies[pos];
					IBizObj backupCompany = backupCompanies.numElements == 1 ? backupCompanies[0] : backupCompanies[pos];
					bool restoreToSameCompany = string.Compare((string)backupCompany.get("shortName"), (string)restoreCompany.get("shortName")) == 0;
				}
			}
			catch (Exception e)
			{
				throw new eComException("error executing restoreCompanyProducts", e);
			}
		}


		public void postExtendEComexecuteCompanyRestore(IApplication app, IRuleContext context, object returnValue, object[] inputParams)
		{
			try
			{
				INameAddressSupport deployInfo = inputParams[2] as INameAddressSupport;
				ZipFile zip = inputParams[3] as ZipFile;
				IResults rc = null;
				rc = context.RuleGroup.execute(context, "restoreCompanyProducts", deployInfo, zip);
				if (rc.ExceptionInfo != null)
					throw rc.ExceptionInfo;
				rc = context.RuleGroup.execute(context, "restoreCheckoutWizards", deployInfo, zip);
				if (rc.ExceptionInfo != null)
					throw rc.ExceptionInfo;
				rc = context.RuleGroup.execute(context, "restorePaymentTerms", deployInfo, zip);
				if (rc.ExceptionInfo != null)
					throw rc.ExceptionInfo;
				rc = context.RuleGroup.execute(context, "restoreTaxesDiscounts", deployInfo, zip);
				if (rc.ExceptionInfo != null)
					throw rc.ExceptionInfo;
				rc = context.RuleGroup.execute(context, "restoreSalesOrders", deployInfo, zip);
				if (rc.ExceptionInfo != null)
					throw rc.ExceptionInfo;
			}
			catch (Exception e)
			{
				throw new eComException("error executing postExtendEComexecuteCompanyRestore.", e);
			}
		}

	}
}
